using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
namespace System.Windows.Interactivity
{
	public abstract class AttachableCollection<T> : DependencyObjectCollection<T>, IAttachedObject where T : IAttachedObject, DependencyObject
	{
		private Collection<T> snapshot;
		private DependencyObject associatedObject;
		protected DependencyObject AssociatedObject
		{
			get
			{
				return this.associatedObject;
			}
		}
		DependencyObject IAttachedObject.AssociatedObject
		{
			get
			{
				return this.AssociatedObject;
			}
		}
		internal AttachableCollection()
		{
			this.add_CollectionChanged(new NotifyCollectionChangedEventHandler(this.OnCollectionChanged));
			this.snapshot = new Collection<T>();
		}
		protected abstract void OnAttached();
		protected abstract void OnDetaching();
		internal abstract void ItemAdded(T item);
		internal abstract void ItemRemoved(T item);
		[Conditional("DEBUG")]
		private void VerifySnapshotIntegrity()
		{
			if (base.get_Count() == this.snapshot.get_Count())
			{
				for (int i = 0; i < base.get_Count(); i++)
				{
					if (base.get_Item(i) != this.snapshot.get_Item(i))
					{
						return;
					}
				}
			}
		}
		private void VerifyAdd(T item)
		{
			if (this.snapshot.Contains(item))
			{
				throw new InvalidOperationException(string.Format(CultureInfo.get_CurrentCulture(), ExceptionStringTable.DuplicateItemInCollectionExceptionMessage, new object[]
				{
					typeof(T).get_Name(),
					base.GetType().get_Name()
				}));
			}
		}
		private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			switch (e.get_Action())
			{
			case 0:
			{
				IEnumerator enumerator = e.get_NewItems().GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						T t = (T)((object)enumerator.get_Current());
						try
						{
							this.VerifyAdd(t);
							this.ItemAdded(t);
						}
						finally
						{
							this.snapshot.Insert(base.IndexOf(t), t);
						}
					}
					return;
				}
				finally
				{
					IDisposable disposable = enumerator as IDisposable;
					if (disposable != null)
					{
						disposable.Dispose();
					}
				}
				break;
			}
			case 1:
				break;
			case 2:
				goto IL_DC;
			case 3:
				return;
			case 4:
				goto IL_191;
			default:
				return;
			}
			IEnumerator enumerator2 = e.get_OldItems().GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					T t2 = (T)((object)enumerator2.get_Current());
					this.ItemRemoved(t2);
					this.snapshot.Remove(t2);
				}
				return;
			}
			finally
			{
				IDisposable disposable2 = enumerator2 as IDisposable;
				if (disposable2 != null)
				{
					disposable2.Dispose();
				}
			}
			IL_DC:
			IEnumerator enumerator3 = e.get_OldItems().GetEnumerator();
			try
			{
				while (enumerator3.MoveNext())
				{
					T t3 = (T)((object)enumerator3.get_Current());
					this.ItemRemoved(t3);
					this.snapshot.Remove(t3);
				}
			}
			finally
			{
				IDisposable disposable3 = enumerator3 as IDisposable;
				if (disposable3 != null)
				{
					disposable3.Dispose();
				}
			}
			IEnumerator enumerator4 = e.get_NewItems().GetEnumerator();
			try
			{
				while (enumerator4.MoveNext())
				{
					T t4 = (T)((object)enumerator4.get_Current());
					try
					{
						this.VerifyAdd(t4);
						this.ItemAdded(t4);
					}
					finally
					{
						this.snapshot.Insert(base.IndexOf(t4), t4);
					}
				}
				return;
			}
			finally
			{
				IDisposable disposable4 = enumerator4 as IDisposable;
				if (disposable4 != null)
				{
					disposable4.Dispose();
				}
			}
			IL_191:
			using (IEnumerator<T> enumerator5 = this.snapshot.GetEnumerator())
			{
				while (enumerator5.MoveNext())
				{
					T current = enumerator5.get_Current();
					this.ItemRemoved(current);
				}
			}
			this.snapshot = new Collection<T>();
			using (IEnumerator<T> enumerator6 = base.GetEnumerator())
			{
				while (enumerator6.MoveNext())
				{
					T current2 = enumerator6.get_Current();
					this.VerifyAdd(current2);
					this.ItemAdded(current2);
				}
			}
		}
		public void Attach(DependencyObject dependencyObject)
		{
			if (dependencyObject != this.AssociatedObject)
			{
				if (this.AssociatedObject != null)
				{
					throw new InvalidOperationException();
				}
				if (Application.get_Current() == null || Application.get_Current().get_RootVisual() == null || !(bool)Application.get_Current().get_RootVisual().GetValue(DesignerProperties.IsInDesignModeProperty))
				{
					this.associatedObject = dependencyObject;
				}
				this.OnAttached();
			}
		}
		public void Detach()
		{
			this.OnDetaching();
			this.associatedObject = null;
		}
	}
}
